package com.ai.vita;

import com.ai.vita.template.TemplateLoader;
import com.al.common.Constant;
import com.al.common.json.Jackson2Converter;
import net.sf.json.JSONObject;
import org.apache.velocity.VelocityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SpringContextHolder;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;

import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 组件抽象类：
 * 1、json处理 jsonConverter
 * 2、组件获取 getComponent
 * 3、调用组件内部方法 invokeMethod
 */
public abstract class AbstractComponent implements IComponent {

    protected static final Logger logger = LoggerFactory.getLogger(AbstractComponent.class);

    //protected JsonConverter jsonConverter = JsonConverter.buildNormalConverter(Constant.DateFormat.DATETIME);
    protected Jackson2Converter jsonConverter = Jackson2Converter.buildNormalConverter(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    private String version;

    protected String getVersion(){
        return this.version;
    }

    public AbstractComponent() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
        this.version = sdf.format(date);
    }

    /**
     * 获取组件实例
     * @param name
     * @return
     */
    protected IComponent getComponent(String name){
        String beanId = "vita." + name;
        IComponent re = null;
        if(SpringContextHolder.containsBean(beanId)){
            re = SpringContextHolder.getBean(beanId);
        }else{
            if(logger.isDebugEnabled()){
                logger.debug("未找到名为{}的组件对象！",name);
            }
        }
        return re;
    }

    /**
     * 方法调用
     * @param owner
     * @param methodName
     * @param args
     * @return
     * @throws Exception
     */
    protected Object invokeMethod(Object owner, String methodName, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class ownerClass = owner.getClass();
        Class[] argsClass = new Class[args.length];
        for (int i = 0, j = args.length; i < j; i++) {
            argsClass[i] = args[i].getClass();
        }
        Method method = ownerClass.getMethod(methodName, argsClass);
        return method.invoke(owner, args);
    }

    /**
     * 组件方法调用
     * @param widgetName
     * @param methodName
     * @param args
     * @return
     */
    protected Object invokeMethod(String widgetName, String methodName, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Object re = null;
        IComponent comp = getComponent(widgetName);
        if(comp != null){
            re = invokeMethod(comp, methodName, args);
        }
        return re;
    }

    /**
     * 调用组件查询数据
     * @param widgetName
     * @param args
     * @return
     */
    protected Map achieveData(String widgetName, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Map options = null;
        IComponent comp = getComponent(widgetName);
        if(comp != null){
            options = (Map)invokeMethod(comp, "achieveData", new Object[]{args});
        }
        return options;
    }

    public String createWidget(Object... params){
        String widgetName = "";
        String templateName = "";
        Map options = new HashMap();
        Boolean needResource = false;
        String classification = null;
        String resources;
        //初始化参数
        for (int i = 0; i < params.length; i++) {
            Object obj = params[i];
            switch (i){
                case 0 :
                    if (obj instanceof String){
                        widgetName = (String)obj;
                        templateName = widgetName + "-tpl";
                    }
                    break;
                case 1 :
                    if (obj instanceof Map){
                        options = (Map)obj;
                    }
                    break;
                case 2 :
                    if (obj instanceof Boolean){
                        needResource = (Boolean)obj;
                    }
                    break;
                case 3 :
                    if (obj instanceof String){
                        classification = (String)obj;
                    }
                    break;
                default : break;
            }
        }
        //开始处理
        if ("".equals(widgetName)){
            return null;
        }else if(TemplateLoader.containTemplate(templateName, "html", classification)){
            VelocityConfigurer vc = SpringContextHolder.getBean("velocityConfigurer");
            VelocityContext ctx = new VelocityContext();
            StringWriter writer = new StringWriter();
            ctx.put("options", JSONObject.fromObject(options));
            resources = TemplateLoader.getTemplate(templateName, "html", classification);
            vc.getVelocityEngine().evaluate(ctx, writer, "", resources);
            if (needResource){
                if(TemplateLoader.containTemplate(widgetName, "js")){
                    String startScript = "script", scriptType = TemplateLoader.getProperties("scriptType");
                    if(scriptType != null){
                        startScript += " type='"+scriptType+"'";
                    }
                    vc.getVelocityEngine().evaluate(ctx, writer, "", "<"+startScript+">"+TemplateLoader.getTemplate(widgetName, "js")+"</script>");
                    if(TemplateLoader.containTemplate(widgetName + ".extend", "js")){
                        vc.getVelocityEngine().evaluate(ctx, writer, "", "<"+startScript+">"+TemplateLoader.getTemplate(widgetName + ".extend", "js")+"</script>");
                    }
                }
                //加载模版对应的样式（css）
                if(TemplateLoader.containTemplate(widgetName, "css")){
                    vc.getVelocityEngine().evaluate(ctx, writer, "", "<style>"+TemplateLoader.getTemplate(widgetName, "css")+"</style>");
                }
            }
            return writer.toString();
        }else {
            return null;
        }
    }

}
